package com.github.chengyuxing.sql.plugins;

import com.github.chengyuxing.common.DataRow;
import com.github.chengyuxing.common.utils.StringUtil;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * Query cache manager.
 */
public interface QueryCacheManager {
    /**
     * Unique key for the cache.
     * <p>It is necessary to ensure uniqueness to avoid cache clutter.</p>
     *
     * @param sql  sql name or sql string
     * @param args args
     * @return the unique key
     */
    default @NotNull String uniqueKey(@NotNull String sql, Map<String, Object> args) {
        String argsStr = Objects.nonNull(args) ? "@" + StringUtil.hash(args.toString(), "MD5") : "";
        if (sql.startsWith("&")) {
            return sql + argsStr;
        }
        return StringUtil.hash(sql, "MD5") + argsStr;
    }

    /**
     * Get cache.
     * <p>Notice: Do not return an empty stream if the cache does not exist.
     * To trigger the execution of a database query, null must be returned.</p>
     *
     * @param uniqueKey unique cache key generated by {@link #uniqueKey(String, Map)}
     * @return cache or null
     */
    Stream<DataRow> get(String uniqueKey);

    /**
     * Put cache.
     *
     * @param uniqueKey unique cache key generated by {@link #uniqueKey(String, Map)}
     * @param value     query result
     */
    void put(@NotNull String uniqueKey, List<DataRow> value);

    /**
     * Check the sql matches the conditions or not, if matches,
     * cache operations {@link #put(String, List) put} and {@link #get(String) get} will be enabling.
     *
     * @param sql  sql name or sql string
     * @param args args
     * @return true or false
     */
    boolean isAvailable(@NotNull String sql, Map<String, Object> args);

}
